<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="SCa9M" id="SCa9M"><span data-lake-id="u14fbf5d9" id="u14fbf5d9">典型回答</span></h1>
  <p data-lake-id="u761ae3a2" id="u761ae3a2"><br></p>
  <p data-lake-id="u677917ec" id="u677917ec"><span data-lake-id="u634f7847" id="u634f7847">推和拉是两种消息传递的方式</span></p>
  <p data-lake-id="u5c323094" id="u5c323094"><span data-lake-id="u821b6858" id="u821b6858">​</span><br></p>
  <p data-lake-id="ue62540c0" id="ue62540c0"><strong><span data-lake-id="u944836f0" id="u944836f0">推的模式</span></strong><span data-lake-id="ue32c1d50" id="ue32c1d50">就消费者端和消息中间件建立TCP长链接或者注册一个回调，当服务端数据发生变化，立即通过这个已经建立好的长连接（或者注册好的回调）将数据推送到客户端。</span></p>
  <p data-lake-id="uf4a470ea" id="uf4a470ea"><strong><span data-lake-id="u4293cb77" id="u4293cb77">​</span></strong><br></p>
  <p data-lake-id="u80f53640" id="u80f53640"><strong><span data-lake-id="ud425591a" id="ud425591a">拉的模式</span></strong><span data-lake-id="u37aa86f0" id="u37aa86f0">就是消费者轮询，通过不断轮询的方式检查数据是否发生变化，变化的话就把数据拉回来。</span></p>
  <p data-lake-id="u489ff889" id="u489ff889"><span data-lake-id="u9c0bfc31" id="u9c0bfc31">​</span><br></p>
  <p data-lake-id="u838cb90b" id="u838cb90b"><span data-lake-id="ud2ac0639" id="ud2ac0639">如果使用拉的模式来实现消息队列的话，消费者可以完全自己掌控消息的数量及速度，这样可以大大的避免消息堆积的情况。但是，这种方案也有缺点，首先就是消费者需要不断的进行轮询，这种轮询也会对消息中间件造成一定的压力。</span></p>
  <p data-lake-id="ub1668414" id="ub1668414"><span data-lake-id="ufe9a6e8c" id="ufe9a6e8c">​</span><br></p>
  <p data-lake-id="u2f8a2710" id="u2f8a2710"><span data-lake-id="u95f3e5a4" id="u95f3e5a4">如果使用推的模式来实现，好处就是消息是实时的， 一旦有消息过来消费者马上就能感知到。而且对于消费者来说也比较简单，不需要轮询，只需要等推送就行了。但是缺点也比较明显，那就是如果消息的生产速度大于消费速度，可能会导致消息大量堆积在消费者端，会对消费者造成很大的压力，甚至可能把消费者压垮。</span></p>
  <p data-lake-id="ue2ba5a8a" id="ue2ba5a8a"><span data-lake-id="u7d916a58" id="u7d916a58">​</span><br></p>
  <p data-lake-id="u67cd2bc3" id="u67cd2bc3"><u><span data-lake-id="u767c4149" id="u767c4149">一般来说，推的模式适合实时性要求比较高的场景。而拉的模式适合实时性要求没那么高的场景。</span></u></p>
  <p data-lake-id="uee567532" id="uee567532"><u><span data-lake-id="u19d93ac7" id="u19d93ac7">​</span></u><br></p>
  <p data-lake-id="u4e527698" id="u4e527698"><u><span data-lake-id="u3760f87d" id="u3760f87d">还有需要注意的就是，在有些生产环境下，服务器环境只能单向通信，也就是只能通过一端访问另外一端，而不能在反方向通信，此时就需要消费方，使用拉模式，推模式是长链接，是双向通信，所以不行。</span></u></p>
  <p data-lake-id="u699a9507" id="u699a9507"><span data-lake-id="u94316d44" id="u94316d44">​</span><br></p>
  <p data-lake-id="u8c4130b7" id="u8c4130b7"><span data-lake-id="u28ad4fe3" id="u28ad4fe3">在很多中间件的实现上，可能并没有在直接用长连接或者轮询，而是把二者结合了一下，使用长轮询的方式进行拉消息的。</span></p>
  <p data-lake-id="ue27b0e7b" id="ue27b0e7b"><span data-lake-id="u0bb81a65" id="u0bb81a65">​</span><br></p>
  <p data-lake-id="u69be7122" id="u69be7122"><strong><span data-lake-id="ue1457787" id="ue1457787">长轮询</span></strong><span data-lake-id="ue1a00c82" id="ue1a00c82">，就是消费者向消息中间件发起一个长轮询请求，消息中间件如果有消息就直接返回，如果没有也不会立即断开连接，而是等待一会，等待过程中如果有新消息到达，再把消息返回。如果超时还没有消息，那就结束了，等下次长轮询。</span></p>
  <p data-lake-id="u96222fa1" id="u96222fa1"><span data-lake-id="u7965d9c3" id="u7965d9c3">​</span><br></p>
  <p data-lake-id="u819763a5" id="u819763a5"><span data-lake-id="uf9451c66" id="uf9451c66">比如Kafka和RocketMQ都是支持基于长轮询进行拉取消息的。</span></p>
 </body>
</html>